//License: Artistic License v2.0, http://opensource.org/licenses/Artistic-2.0

package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
)

const sep = string(os.PathSeparator)

var projName string
var snippets = map[string](map[string]string){} //usage: snippets["SiteNav"]
var supportedLang = map[string]bool{}           //usage: supportedLang["fr"]
var copies = map[string]Copy{}                  //usage: copies["i-am-gobl"]
var htmlContents = map[string]Content{}
var staticContents = map[string]Content{}

var conf struct {
	DefaultLang          string
	HTTPServerPort       string
	MsgConnType          string
	MsgConnAddr          string
	TLSServerPort        string
	TLSCertFile          string
	TLSKeyFile           string
	Domain               string
	IPTableFile          string
	Theme                string
	ServeTLS             bool
	ServeLiveUpdate      bool
	ServeHTTPLogging     bool
	TrackLocation        bool
	BlogsPerPage         int
	SearchResultsPerPage int
	IPToColumn           int
	IPCityColumn         int
	IPAreaColumn         int
	IPCountryColumn      int
}

var logger struct {
	LogConnType         string
	LogConnAddr         string
	LogConnBufSize      int
	LogWriteImmediately bool
}

func main() {
	flag.Parse()
	switch flag.Arg(0) {
	case "ws":
		startWebServer(flag.Arg(1))
	case "update":
		updateWebServer(flag.Arg(1), flag.Arg(2), flag.Arg(3))
	case "ls":
		startHTTPLogServer()
	case "init":
		fmt.Println(initProj(flag.Arg(1), flag.Arg(2), flag.Arg(3)))
	case "theme":
		fmt.Println(setTheme(flag.Arg(1), flag.Arg(2)))
	case "set":
		fmt.Println(manageUser("set", flag.Arg(1), flag.Arg(2)))
	case "test":
		fmt.Println(manageUser("test", flag.Arg(1), flag.Arg(2)))
	case "add":
		fmt.Println(addCopy(flag.Arg(1), flag.Arg(2), flag.Arg(3)))
	case "rm":
		fmt.Println(rmCopy(flag.Arg(1), flag.Arg(2)))
	case "example":
		fmt.Println(showTextFile(path("exampleFile")))
	case "help":
		fmt.Println(showTextFile(path("readmeFile")))
	default:
		fmt.Println(showTextFile(path("readmeFile")))
	}
	os.Exit(0)
}

func updateWebServer(name, user, password string) { //live update server content (hot swap)
	if name == "" {
		fmt.Println(showTextFile(path("readmeFile")))
		return
	}
	projName = name
	if err := readConfigFile(path("configFile")); err != nil {
		panic(err)
	}
	if conf.ServeLiveUpdate {
		log.Println(projName, "Sending message to", conf.MsgConnType, conf.MsgConnAddr)
		var msg []string = ToSlice("update", user, password)
		SendMsg(msg, conf.MsgConnType, conf.MsgConnAddr)
	} else {
		log.Println(projName, "Doing nothing ... because LiveUpdate is off")
	}
}

func startHTTPLogServer() { //start or turn on _msgServer_ to accept inbound log msgs
	log.Println("log server", "Loading log connection config")
	if err := Json("get", path("connectionConfigFile"), &logger); err != nil {
		log.Println("log server", "Err reading", path("connectionConfigFile"))
		return
	}
	log.Println("log server", "Starting HTTP log listener")
	const secondsBeforeRetry = 3 //if first try fails
	var inboundHttpLog net.Listener = SetListener(logger.LogConnType, logger.LogConnAddr, secondsBeforeRetry)
	SaveToFile(&inboundHttpLog, path("log"), "hlog", "csv", logger.LogConnBufSize, logger.LogWriteImmediately)
}

func startWebServer(name string) {
	if name == "" {
		fmt.Println(showTextFile(path("readmeFile")))
		return
	}
	projName = name
	var err error = readConfigFile(path("configFile"))
	if err != nil {
		panic(err)
	}
	err = readDataFiles()
	if err != nil {
		log.Println(projName, "Init / restore failed")
		panic(err)
	}
	if conf.ServeLiveUpdate {
		log.Println(projName, "Listening to LiveUpdate at", conf.MsgConnType, conf.MsgConnAddr)
		const secondsBeforeRetry = 3
		var msgListener net.Listener = SetListener(conf.MsgConnType, conf.MsgConnAddr, secondsBeforeRetry)
		go listenToUpdate(&msgListener)
	}
	staticContents = loadStaticContents()
	htmlContents = loadAssembledContents(&copies)
	for urlPath, _ := range staticContents {
		http.HandleFunc(urlPath, getStatic)
	}
	http.HandleFunc("/search/", search)
	http.HandleFunc("/blog/", search)
	http.HandleFunc("/tag/", search)
	http.HandleFunc("/", getPage)
	if conf.ServeHTTPLogging {
		log.Println(projName, "Loading log connection config")
		if err := Json("get", path("log")+"connectionConfig.json", &logger); err != nil {
			log.Println(projName, "Err reading log connectionConfig.json")
			panic(err)
		}
	}
	if conf.ServeTLS {
		log.Println(projName, "Starting HTTPS server at port", conf.TLSServerPort)
	} else {
		log.Println(projName, "Starting HTTP server at port", conf.HTTPServerPort)
	}

	var sysLog os.File = newLog(path("log"), "slog", "log")
	log.SetOutput(&sysLog)
	defer sysLog.Close()

	if conf.ServeTLS {
		http.ListenAndServeTLS(conf.TLSServerPort, conf.TLSCertFile, conf.TLSKeyFile, nil)
	} else {
		http.ListenAndServe(conf.HTTPServerPort, nil)
	}
}

//Copyright: Slamet Hendry
//Thank you Rick Morrison for updating lib usages in 0.1.x from r60 to weekly.2012-02-22
//	- strconv: Itoa64 to FormatInt
//	- time: Seconds to Now().Unix()
//	- http.Request: RawURL to URL.Path & URL.String()
//	- runtime: MemStats to ReadMemStats (later I dropped this)
//	- os.Error to error
//	- hmac: NewSHA256 to New
